package com.example.kotlindemo.demo

/**
 * 类和对象
 * 1.类的定义
 * 2.类的属性：getter 和setter
 * 3.主构造器和次构造器
 * 4.抽象类
 * 5.嵌套类
 * 6.内部类
 * 7.匿名内部类
 * 8.类的修饰符
 */

class Unit5() {
    /**
     * 类的定义
     */
    class A //表示一个空的类
    class A1 {
        fun test() {//类中的方法
            println("测试")
        }
    }

    /**
     * 一、类的属性
     * 1.Kotln中没有new关键字
     * 2.要是用一个属性只要引用他的名称就可以了
     * 3.一个类可以有一个主构造器，以及多个次构造器
     */
    class B {
        var name: String = ""
        var age: Int = 0
        var height: Float = 180.0f
    }

    class B1 constructor(name: String) {//如果主构造器没有注解，也没有修饰符那么constructor关键字可以省略掉
    }

    /**
     * 二、getter 和 setter
     * 1.getter 和 setter 都是可选
     * 2.如果参数设置为val的话，则不可以设置为setter，因为他是只读取的
     * 3.Kotlin 中类不能有字段。提供了 Backing Fields(后端变量) 机制,备用字段使用field关键字声明,field 关键词只能用于属性的访问器
     */
    class C {
        private var name: String = ""
            set(value) {
                field = value
            }
            get() {
                return field
            }
    }

    class C1 {
        lateinit var name: String//lateinit 定义暂时没有初始化的数据
        fun setUserName(name1: String) {
            this.name = name1
        }
    }

    /**
     * 三、主构造器
     * 1.主构造器中的不能包含代码，初始化的代码可以放在初始化的代码段中，使用init关键字作为前缀
     * 2.如果构造器有注解，或者有可见度修饰符，这时constructor关键字是必须的，注解和修饰符要放在它之前。
     */
    class D constructor(name: String) {
        init {
            //主构造器中的不能包含代码，初始化的代码可以放在初始化的代码段中，使用init关键字作为前缀
            println("初始化D类")
        }
    }

    //实例
    class D1 constructor(name: String, age: Int) {
        var name: String = name
        var age: Int = age

        init {
            println("初始化JSON数据 = User{'name'=$name,'age'=$age}")

        }
    }

    /**
     * 次级构造函数
     * 1.需要加前缀constructor
     */
    class D2 constructor(val name: String) {
        init {
            println("初始化D2")
            var d2 = D2("12", 12)
        }
       private constructor(name: String,age: Int) : this(name) {//次级构造函数,添加private表示该函数是私有函数，外界无法访问
            println("调用次级构造函数")
        }
        fun testD2(){
            println("test")
        }
    }
    /**
     * 四、抽象类
     * 1.使用abstract标注
     * 2.抽象的类不可以被创建对象
     */
    open class E{
        open fun foo(){
            println("E")
        }
    }
    abstract class E1 :E(){ //继承了E，格式 :cls()
        override fun foo() {//重写方法
            println("E1")
        }
    }
    class E2: E1() {
        override fun foo() {
            super.foo()

        }
    }
    /**
     * 五、嵌套类
     */
    class F{
        class F1{
            class F2{

            }
        }
    }
    fun testF(){
        var f = F()
        var f1 = F.F1()
        var f2 = F.F1.F2()
    }
    /**
     * 六、内部类
     */
    class G constructor(name: String){
        init {
            println("init G")
        }
        constructor(name: String,age: Int):this(name){

        }
        fun testG(){
            println("test G")
        }
        inner class G1 constructor(name: String){
            init {
                println("init G1")
            }
            constructor(name: String,age: Int):this(name){

            }
            fun testG1(){
                println("test G1")
            }
        }
    }
    /**
     * 七、匿名内部类
     */
    class H1{
       fun addCallBack(callBack: CallBack){
           callBack.onA("小明")
       }
        fun testH1(){
            //第一种写法
            this.addCallBack(object:CallBack{
                override fun onA(str:String) {
                    println(str)
                }

            })
            //第二种写法
//           this.addCallBack{v:String -> println(v)}
        }
    }


    /**
     * 八、类的修饰符
     * abstract 抽象类
     * final 类不可以继承
     * enum 枚举类
     * open 继承类，默认final
     * annotation 注解类
     */






}